<?php

if (!defined('BASEPATH'))
    exit('No direct script access allowed');

class Modelo extends CI_Model {

    protected $tabla;

    public function __construct() {
        // Call the Model constructor
        parent::__construct();
    }

    /**
     * Metodo para levantar un item de la base de datos por id
     * @param integer $id el id del objeto a levantar
     * @return boolean falso si hubo error, true si tuvo exito
     */
    public function get($id) {
        $results = $this->db->get_where($this->tabla, array('id' => $id));
        $data = $results->result_array();

        if (empty($data)) {
            return false;
        } else {
            $this->setAttributes($data[0], 'array');
        }
        return true;
    }

    /**
     * Guarda la instancia en la base de datos.
     * @return boolean true o false si tuvo exito o no.
     */
    public function save() {
        $ret = '';
        if ($this->id == '' || $this->id == null) {
            $this->db->insert($this->tabla, $this);
            $ret = $this->db->insert_id();
            $this->id = $ret;
        } else {
            $this->db->update($this->tabla, $this, "id = $this->id");
            $ret = $this->db->affected_rows();
        }

        return $ret;
    }

    /**
     * Borrado fisico de la instancia en la base de datos.
     * @return boolean true o false dependiendo si borro o no.
     */
    public function delete() {
        if ($this->id == '')
            return false;

        $this->db->delete($this->tabla, array('id' => $this->id));
        return $this->db->affected_rows();
    }

    /**
     * Borrado logico de la instancia en la base de datos.
     * @return boolean true o false dependiendo si borro logicamente o no.
     */
    public function deleteLogico($fieldname = 'estado') {
        if ($this->id == '')
            return false;

        $this->db->update($this->tabla, array($fieldname => 0), array('id' => $this->id));
        return $this->db->affected_rows();
    }

    /**
     * Borrado logico de la instancia en la base de datos.
     * @return boolean true o false dependiendo si borro logicamente o no.
     */
    public function activeLogico($fieldname = 'estado') {
        if ($this->id == '')
            return false;

        $this->db->update($this->tabla, array($fieldname => 1), array('id' => $this->id));
        return $this->db->affected_rows();
    }

    /**
     * No lo definimos como abstract porque sino la clase deberia tambien
     * ser abstract y entonces no la podemos levantar como un modelo.
     */
    protected function setAttributes() {
        
    }

    /**
     * Setea cada atributo de la instancia con los datos que se le envian.
     * Chequea que existan las variables donde va a guardar lo que se le pasa.
     *
     * @param string $clase nombre de la clase hija que llama a esta funcion
     * @param array $datos los datos a guardar
     * @param string $tipo tipo del parametro $datos. puede ser object o array.
     * @return void
     */
    final protected function _setAttributes($clase = null, $datos = array(), $tipo = 'object') {
        $attributes = get_class_vars($clase);
        foreach ($attributes as $key => $value):
            if ($key == 'tabla')
                continue;
            if ($tipo == 'object') {
                $this->$key = $datos->post($key);
            } else {
                $this->$key = $datos["$key"];
            }
        endforeach;

        return;
    }

    protected function doArray() {
        
    }

    final protected function _doArray($clase = null) {
        $attributes = get_class_vars($clase);
        $array = array();
        foreach ($attributes as $key => $value):
            $array[$key] = $this->$key;
        endforeach;

        return $array;
    }

    /**
     * Metodo estatico que devuelve una lista de instancias de la clase.
     * @param array $where
     * @param array $order_by
     * @param integer $offset
     * @param integer $limit
     */
    public function getList($where = array(), $order_by = array(), $offset = 0, $limit = -1) {
        $this->db->from($this->tabla);
        $this->db->where($where);

        if (!empty($order_by))
            foreach ($order_by as $field => $order)
                $this->db->order_by($field, $order);

        if ($limit != -1)
            $this->db->limit($limit, $offset);

        $results = $this->db->get();

        return $results->result_object();
    }

    /**
     * Guarda la instancia en la base de datos.
     * @return boolean true o false si tuvo exito o no.
     */
    public function logs($tipo, $usuarioId, $log) {
        
        $log->tipo = $tipo;
        $log->tabla = $this->tabla;
        $log->tablaId = $this->id;
        $log->datos = json_encode($this);
        $log->usuarioId = $usuarioId;
        $log->visto = 0;

        $this->db->insert('log', $log);
        $ret = $this->db->insert_id();

        return $ret;
    }

}